/**
 * @class NG.models.QueryMode 
 * @extends {Ext.data.Model}
 * 
 * This model used by map queries. This is constructed in map view. 
 * There are five modes. These are:<br>
 * <li>Point
 * <li>Area
 * <li>Shortest path
 * <li>Measure distance
 * <li>Calculate Area
 * <br>
 * You can add extra modes expilicitly in map view.<br>
 * Model of info query mode is registered as 'NG.models.QueryMode'.<br>
 */
NG.models.QueryMode = Ext.regModel("NG.models.QueryMode", {
	
	/**
	 * Fields of info model:<br>
	 * <li>name
	 * <li>mode
	 * <li>className css style class name. Default value is 'blank'.
	 * @property fields
	 * @type Array
	 */
    fields: [
        {name: "name", type: "string"},
        {name: "mode", type: "string"},
        {name: "className", type: "string", defaultValue: 'blank'}
   	],
   	
   	/**
   	 * @private
   	 */
   	phantom: true,
   	
   	/**
   	 * 
   	 * @return {String}
   	 */
   	getName: function (){return this.data.name;},
   	
   	/**
   	 * 
   	 * @return {String}
   	 */
   	getMode: function (){return this.data.mode;},
   	
   	/**
   	 * 
   	 * @return {String} Html tag class name. Class names are defined in netgis.css file.
   	 */
   	getClassName: function (){return this.data.className;},

   	/**
   	 * This method is called when a model is being listed in a List.
   	 * 
   	 * @return {String} Text when query mode is being listed in a List view 
   	 */
   	getTableDisplayValue: function (){
   		return this.getName();
   	}
});

/**
 * @class NG.models.Info
 * @extends Ext.data.Model
 * 
 * Info model is used to query map for summary results.<br>
 * Model of info is registered as 'NG.models.Info'.
 */
NG.models.Info = Ext.regModel("NG.models.Info", {
	
	/**
	 * Fields of info model:<br>
	 * <li>id
	 * <li>featureMember
	 * <li>rowsCount
	 * <li>propertyList: Array
	 * <li>detailList: Array. Handles info detail List.
	 * <li>detailCache: Array. Handles info detail List.
	 * 	  
	 * @property fields
	 * @type Array
	 */		
    fields: [
        {name: "id", type: "int"},
        {name: "featureMember", type: "string"},
        {name: "rowsCount", type: "int"},
        {name: "propertyList", defaultValue: []},
        {name: "detailList", defaultValue: []},
        {name: "detailCache", defaultValue: []} //InfoDetail list
   	],
   	
   	/**
   	 * @private
   	 */
   	phantom: true,
   	
   	/**
   	 * 
   	 * @return {Number} Id of the model.
   	 */
   	getId: function (){return this.data.id;},
   	
   	/**
   	 * 
   	 * @return {String} Feature name.
   	 */
   	getFeatureName: function (){return this.data.featureMember;},
   	
   	/**
   	 * 
   	 * @return {Number} Rows count.
   	 */
   	getRowsCount: function (){return this.data.rowsCount;},
   	
   	/**
   	 * 
   	 * @param {Integer} rowsCount It must be integer.
   	 */
   	setRowsCount: function (rowsCount){this.data.rowsCount = rowsCount;},
   	
   	/**
   	 * 
   	 * @return {Array} Array of property.
   	 */
   	getPropertyList: function() {return this.data.propertyList;},
   	
   	/**
   	 * If an info is queried for details, query result is cached.
   	 * 
   	 * @return {Array} Array of {@link NG.models.InfoDetail}
   	 */
   	getDetailCache: function() {return this.data.detailCache;},
   	
   	/**
   	 * 
   	 * @param {Array} detailList Array of NG.models.InfoDetail
   	 */
   	setDetailCache: function(detailList) {this.data.detailCache = detailList;},
   	
   	/**
   	 * 
   	 * @return {Array} Array of {@link #NG.models.InfoDetail}
   	 */
   	getDetailList: function() {return this.data.detailList;},
   	
   	/**
   	 * Adds property to property list.
   	 * @param {String} property 
   	 */
   	addProperty: function(property) {this.data.propertyList.push(property);},
   	
   	/**
   	 * Adds a detail to detailList.
   	 * @param {NG.models.InfoDetail} detail
   	 */
   	addDetail: function(detail) {this.data.detailList.push(detail);},

   	/**
   	 * Removes detail from detail list of the model.
   	 * @param {NG.models.InfoDetail} detail
   	 */
   	removeDetail: function(detail) {
   		var detailList = this.getDetailList();
   		for(var i=0; i<detailList.length;i++ ) { 
   			if(detailList[i] == detail) {
   				detailList.splice(i,1);    				
   			}
   		} 
   	},

   	/**
   	 * This method is called when a model is being listed in a List.
   	 * 
   	 * @return {String} Text when info is been listing in a List view 
   	 */
   	getTableDisplayValue: function (){
   		return this.getFeatureName();
   	}
});


/**
 * @class NG.models.InfoDetail
 * @extends Ext.data.Model
 *  
 * Each info has info details.<br>
 * InfoDetail value list members maps to propertyNames under Info.<br>
 * Model of info detail is registered as 'NG.models.InfoDetail'.<br>
 */
NG.models.InfoDetail = Ext.regModel("NG.models.InfoDetail", {
	/**
	 * Fields of info detail model:<br>
	 * <li>objectID
	 * <li>valueList: Array
	 * <li>geometryMember
	 * <li>parent: NG.models.Info
	 * <li>htmlContent
	 * 
	 * @property fields
	 * @type Array
	 */	
    fields: [
        {name: "objectID", type: "string"},
        {name: "valueList", defaultValue: []},
        {name: "geometryMember"},
        {name: 'parent'}, //NG.models.Info
        {name: "htmlContent"}
   	],
   	phantom: true,
   	
   	/**
   	 * 
   	 * @param {String} detailID
   	 */
   	setObjectID: function (detailID){this.data.objectID = detailID;},
   	
   	/**
   	 * 
   	 * @return {String}
   	 */
   	getObjectID: function (){return this.data.objectID;},
   	
   	/**
   	 * Adds value to valueList field.
   	 * @param {String} value
   	 */
	addValue: function (value){this.data.valueList.push(value);},
	
	/**
	 * 
	 * @return {Array}
	 */
   	getValueList: function (){return this.data.valueList;},
   	
   	/**
   	 * geoMember: [NG.models.NGPolygon, NG.models.NGPoint, NG.models.NGLine]
   	 * 
   	 * @param {Object} geoMember
   	 */
   	setGeometry: function (geoMember){this.data.geometryMember = geoMember;},
   	
   	/**
   	 * 
   	 * @return {Object} [NG.models.NGPolygon, NG.models.NGPoint, NG.models.NGLine]
   	 */
   	getGeometry: function (){return this.data.geometryMember;},
   	
   	/**
   	 * If it is wanted to change list item visual, this method must be extended.
   	 * After preparation of html content <b>htmlContent</b> field is set by content.<br>
   	 * Just at most 4 fields are displayed on screen. For detail use popup action list by swaping the list item.
   	 *  
   	 * @return {String} Html content when model is being listed.
   	 */
   	prepareHTMLContent: function () {
   		var propList = this.data.parent.getPropertyList();
		var result = '<table width="250px">';

   		for (var i=0; i<(propList.length < 4 ? propList.length : 4) ; ++i ) {
   			result +  "<tr>";
   			result += "<td><b>" + propList[i] + "<b></td>";
   			result += "<td>" + this.data.valueList[i] + "</td>";
   			result += "</tr>";
   			//result += '<b>' + propList[i] + "</b>:&nbsp;" + this.data.valueList[i] + "<br/>"; 
   		}
   		result += "</table>";
   		
   		this.setHTMLContent(result);
   		return result;
   	},
   	
   	/**
   	 * For example MAHALLE_ADI is property, this method returns the value of MAHALLE_ADI as 'Kavaklıdere'.
   	 * @param {String} property
   	 * @return {String} value f the property. Returns null if property is not found.
   	 */
   	getValueOfProperty: function (property){
   		if ("OBJECTID" === property)
   			return this.getObjectID();
   		var propList = this.data.parent.getPropertyList();
   		
   		for (var i=0; i < propList.length; ++i ) {
   			if (propList[i] === property)
   				return this.data.valueList[i];
   		}  
   		return null;
   	},
   	
   	setValueOfProperty: function (property, value){
   		if ("OBJECTID" === property)
   			return;
   		var propList = this.data.parent.getPropertyList();
   		
   		for (var i=0; i < propList.length; ++i ) {
   			if (propList[i] === property) {
   				this.data.valueList[i] = value;
   				break;
   			}
   		}  
   	},
   	
   	/**
   	 * Sets html content. Html content can be set explicitly.<br>
   	 * For example from SearchView preperations.<br>
   	 * Html content is set also by {@link #prepareHTMLContent}
   	 * 
   	 * @param {String} content Html formated string
   	 * 	
   	 */
   	setHTMLContent: function (content){
   		this.data.htmlContent = content;
   	},
   	
   	/**
   	 * prepareHtmlContent method should be called before.
   	 * @return {String}
   	 */
   	getHTMLContent: function (){
   		return this.data.htmlContent;
   	},

   	
   	/**
   	 * Sets parent field of model.
   	 * 
   	 * @param {NG.models.Info} parentInfo
   	 */
   	setParent: function(parentInfo){this.data.parent = parentInfo;},

   	/**
   	 * 
   	 * @return {NG.model.Info} parent of the detail. 
   	 */
   	getParent: function(){return this.data.parent;},
   	
   	/**
   	 * This method is called when a model is being listed in a List.
   	 * 
   	 * @return {String} Text when info detail is being listed in a List view 
   	 */
   	getTableDisplayValue: function (){
   		return this.getObjectID();
   	},
   	
   	/**
   	 * Primary key field is the key whose isKey property is 1.
   	 * @return {String} primary key field name. If none is found null.
   	 */
   	getPrimaryKeyFieldName: function (){
   		var fadList = app.views.searchView.getGetInfoExCommand().FAD;
   		
   		//find related fad according to this.getParent().getFeatureName();
   		var fad = null;
   		var featureName = this.getParent().getFeatureName();
   		for ( var i = 0; i < fadList.length; i++) {
			if (featureName === fadList[i].getTableName()) {
				fad = fadList[i];
				break;
			}
		}
   		
   		if (fad == null) {
   			alert("getPrimaryKeyFieldName fad bulunamadı.");
   			return null;
   		}
   		
   		var fieldList = fad.getFieldList();
   		for ( var i = 0; i < fieldList.length; i++) {
			if (fieldList[i].isKey()) {
				return fieldList[i].getFieldName();
			}
		}
   		
   		return null;
   	},
   	
   	/**
   	 * Returns string representation of info detail.
   	 * 
   	 * @return {String}
   	 */
   	toString: function (){
   		return "[ObjID: " + this.getObjectID() + ", ValueList: (" + this.getValueList() + ") " + "]";
   	},
   	
   	/**
   	 * Model name for Put info ex 
   	 * @private
   	 */
   	_RECORD_MODEL_NAME: 'NG.models.InfoDetail-Record',
   	
   	/**
   	 * Record for Put info ex.
   	 * @private
   	 */
   	_RECORD: null,
   	
   	refreshRecordForPutInfoEx: function(){
   		this._RECORD = null;
   	},
   	
   	/**
   	 * Creates form items for display or update of the info detail record. Once created record is assigned to _RECORD.
   	 * If you want to refresh that record you must call <pre>refreshRecordForPutInfoEx</pre>
   	 */
   	getRecordForPutInfoEx: function () {
   		if (this._RECORD) return this._RECORD;
   		var propList = this.getParent().getPropertyList();
   		var modelFieldArray = [];
   		var modelValueObject = {};
   		var formItems = [];
   		for (var i=0; i < propList.length; ++i ) {
   			//result += '<b>' + propList[i] + "</b>:&nbsp;" + this.data.valueList[i] + "<br/>";
   			var key = propList[i];
   			var value = this.data.valueList[i];
   			formItems.push({
                xtype: 'textfield',
                label: key,
                //placeHolder: key,
                name: key
                //value: infoDetail.data.valueList[i],
                //TODO editable özelliğine göre, alanlara default ekle
            });
			modelFieldArray.push(key);
			modelValueObject[key] = value;
   		}

    	Ext.regModel(this._RECORD_MODEL_NAME, {
    	    fields: modelFieldArray,
    	    modifiedFields: new Ext.util.HashMap(),
    	    formItems: formItems,
    	    phantom: true
    	});        	
    	var record = Ext.ModelMgr.create(modelValueObject, this._RECORD_MODEL_NAME);
    	this._RECORD = record;
    	return record;
   	}
   	
});